package xvalidator

import (
	"errors"
	"gitee.com/igolang/pkg/xlog"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/validator/v10"

	"reflect"
)

var log = xlog.DefaultStdLog()

type Validator interface {
	GetMessages() map[string]map[string]error
}

type CustomValidator struct {
	Tag  string
	Func validator.Func
}

// RegisterCustomValidation 注册自定义验证器，非线程安全
func RegisterCustomValidation(cv ...*CustomValidator) {
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		for _, vv := range cv {
			if err := v.RegisterValidation(vv.Tag, vv.Func); err != nil {
				log.Printf("register custom validator err, tag: %s, err: %v\n", vv.Tag, err)
			} else {
				log.Printf("register custom validator: %#v\n", vv)
			}
		}
	}
}

func FormatValidatorError(request Validator, err error, tag string) error {
	var value validator.ValidationErrors
	ok := errors.As(err, &value)
	if !ok {
		return err
	}

	t := reflect.TypeOf(request)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	messages := request.GetMessages()

	for _, v := range value {
		fieldName := v.Field()
		if t.Kind() == reflect.Struct && tag != "" {
			if field, ok := t.FieldByName(fieldName); ok {
				if tagValue := field.Tag.Get(tag); tagValue != "" {
					fieldName = tagValue
				}
			}
		}

		if msgVal, exist := messages[fieldName]; exist {
			return msgVal[v.Tag()]
		}

	}

	return err
}

func FormatError(request any, err error) error {
	var value validator.ValidationErrors
	ok := errors.As(err, &value)
	if !ok {
		return err
	}

	t := reflect.TypeOf(request)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	if t.Kind() != reflect.Struct {
		return err
	}

	for _, v := range value {
		fieldName := v.Field()
		if field, ok := t.FieldByName(fieldName); ok {
			if tagValue := field.Tag.Get("validator_msg"); tagValue != "" {
				return errors.New(tagValue)
			}
		}
	}

	return err
}
